import json
import os

from django.conf import settings
from util.change_to_e import change_to_e, r_control


class JsonDeal:
    if not os.path.isdir(settings.TEMP_FILE_DIR):
        os.mkdir(settings.TEMP_FILE_DIR)

    @classmethod
    def read_file(cls, file_path):
        lines = []
        index = 0
        cut_index = []
        file_names = []
        with open(file_path, "r", encoding="utf-8") as f:
            while True:
                line = f.readline()
                if line:
                    lines.append(line)
                    if line.startswith("<filename"):
                        cut_index.append(index)
                        file_name = line.split("=")[-1][:-1]
                        file_names.append(file_name)
                    index += 1
                else:
                    break
        return lines, cut_index, file_names

    @classmethod
    def file_to_json(cls, lines, cut_index, file_names):
        json_datas = {}
        for i in range(len(cut_index)):
            try:
                control = lines[cut_index[i] + 1: cut_index[i + 1]]
            except:
                try:
                    control = lines[cut_index[i] + 1:]
                except Exception as e:
                    raise e
            json_datas[file_names[i]] = control
        for file_name, control in json_datas.items():
            data = ""
            for i in control:
                data += i
            data = json.loads(data)
            controls = data.get("data")
            for control in controls:
                control["filename"] = file_name
            json_datas[file_name] = data
        return json_datas

    @classmethod
    def cut_and_json(cls, json_datas):
        new_json = {"data": []}
        for json_data in json_datas.values():
            data = json_data.get("data")
            for item in data:
                new_json.get("data").append(item)
        return new_json

    @classmethod
    def explain_to_qianduan(cls, explain_content, origin_content):
        explain_datas = explain_content.get("data")
        origin_datas = origin_content.get("data")
        need_group_names = []
        for origin_item in origin_datas:
            group_name = origin_item.get("group")
            for explain_item in explain_datas:
                if explain_item.get("group") == group_name:
                    explain_control = explain_item.get("controls")
                    origin_control = origin_item.get("controls")
                    explain_item["filename"] = origin_item.get("filename")
                    enable = origin_item.get("enable")
                    if enable is not None:
                        if enable == "false":
                            explain_item["controls"] = []
                        else:
                            explain_item["controls"] = cls.explain_json(explain_control, origin_control)
                    else:
                        if origin_control:
                            explain_item["controls"] = cls.explain_json(explain_control, origin_control)
                        else:
                            explain_item["controls"] = []
                    need_group_names.append(group_name)
        need_groups = []
        for explain_item in explain_datas:
            if explain_item.get("group") in need_group_names:
                need_groups.append(explain_item)
        new_explain_datas = {"data": []}
        for need_group in need_groups:
            new_explain_datas.get("data").append(need_group)
        return new_explain_datas, origin_datas

    @classmethod
    def explain_json(cls, explain_control, origin_control):
        neep_nodes_or_extends = []
        for origin_item in origin_control:
            origin_name = origin_item.get("name")
            for explain_item in explain_control:
                explain_name = explain_item.get("name")
                if origin_name == explain_name:
                    neep_nodes_or_extends.append(origin_name)
                    if explain_item.get("value") is not None:
                        explain_item["value"] = origin_item.get("value")
                    else:
                        explain_node = explain_item.get("node")
                        origin_node = origin_item.get("node")
                        explain_extend = explain_item.get("extend")
                        origin_extend = origin_item.get("extend")
                        if origin_node:
                            cls.explain_node_json(explain_node, origin_node)
                        if origin_extend:
                            cls.explain_node_json(explain_extend, origin_extend)
        need_nodes = []
        for explain_item in explain_control:
            if explain_item.get("name") in neep_nodes_or_extends:
                need_nodes.append(explain_item)
        return need_nodes

    @classmethod
    def explain_node_json(cls, explain_node, origin_node):
        for origin_item in origin_node:
            origin_name = origin_item.get("name")
            for explain_item in explain_node:
                if explain_item.get("name") == origin_name:
                    if explain_item.get("value") is not None:
                        explain_item["value"] = origin_item.get("value")

    @classmethod
    def explain_to_tia(cls, content):
        new_data = []
        exists_data = content
        for item in exists_data:
            new_item = {}
            new_item["group"] = item.get("group")
            new_item["filename"] = item.get("filename")
            new_item["enable"] = item.get("enable")
            new_item["controls"] = cls.get_control_data(item.get("controls"))
            new_data.append(new_item)
        new_content = {
            "data": new_data
        }
        return new_content

    @classmethod
    def get_control_data(cls, controls):
        new_controls = []
        for control in controls:
            item = {}
            item["name"] = control.get("name")
            if control.get("value"):
                item["value"] = control.get("value")
            elif control.get("node"):
                item["node"] = cls.get_node_data(control.get("node"))
            elif control.get("extend"):
                item["extend"] = cls.get_node_data(control.get("extend"))
            new_controls.append(item)
        return new_controls

    @classmethod
    def get_node_data(cls, nodes):
        new_node = []
        for node in nodes:
            item = {}
            item["name"] = node.get("name")
            item["value"] = node.get("value")
            new_node.append(item)
        return new_node

    @classmethod
    def cut_json_file(cls, content):
        datas = content.get("data")
        file_names = []
        for item in datas:
            file_names.append(item.get("filename"))
        file_names = list(set(file_names))
        json_files = {}
        for i in range(len(file_names)):
            file_name = file_names[i]
            json_files[file_name] = cls.find_data(file_name, datas)
        for name, values in json_files.items():
            cls.struct_new_json(name, values)
        return list(json_files.keys())

    @classmethod
    def find_data(cls, file_name, datas):
        cut_datas = []
        for item in datas:
            if file_name == item.get("filename"):
                cut_datas.append(item)
                item.pop("filename")
        return cut_datas

    @classmethod
    def struct_new_json(cls, name, list_data):
        new_data = {"data": []}
        new_data["data"] = list_data
        file_name = "".join([settings.TEMP_FILE_DIR, "/", name])
        with open(file_name, "w", encoding="utf-8")as f:
            json.dump(new_data, f)
        return new_data

    @classmethod
    def change_to_file(cls, filenames, file_path, is_old=False):
        with open(file_path, "w", encoding="utf-8") as f:
            if is_old:
                f.write("<version:02>\n")
            else:
                f.write("<version:01>\n")
            for name in filenames:
                part_file_path = "".join([settings.TEMP_FILE_DIR, "/", name])
                f.write("".join([name, "\n"]))
                with open(part_file_path, "r", encoding="utf-8") as part_f:
                    line = part_f.readline()
                    new_line = line.replace("{", "{\n")
                    new_line = new_line.replace(", ", ",\n")
                    new_line = new_line.replace("}", "\n}\n")
                    new_line = new_line.replace("[", "\n[")
                    f.write(new_line)

    @classmethod
    def get_new_json(cls, file_path):
        try:
          with open(file_path) as f:
            content = json.load(f)
          origin_content = change_to_e(content,r_control)
        except:
          lines, cut_index, file_names = JsonDeal.read_file(file_path)
          json_dats = JsonDeal.file_to_json(lines, cut_index, file_names)
          origin_content = JsonDeal.cut_and_json(json_dats)
        return origin_content

    @classmethod
    def get_qianduan(cls, explain_file_path, origin_content):
        file_path = "".join([settings.JSON_CONFIG_FILE_PATH, "/", settings.JSON_EXPLAIN_FILE])
        with open(file_path, "r", encoding="utf-8") as f:
            explain_content = json.load(f)
        explain_datas, _ = JsonDeal.explain_to_qianduan(explain_content, origin_content)
        with open(explain_file_path, "w", encoding="utf-8") as f:
            json.dump(explain_datas, f)
        return explain_datas

    @classmethod
    def get_old_qianduan(cls,explain_file_path, content):
        explain_datas = content
        with open(explain_file_path, "w", encoding="utf-8") as f:
            json.dump(explain_datas, f)
        return explain_datas

    @classmethod
    def get_tia(cls, explain_content, file_path):
        new_content = cls.explain_to_tia(explain_content)
        file_names = cls.cut_json_file(new_content)
        cls.change_to_file(file_names, file_path)
        for name in file_names:
            part_file_path = "".join([settings.TEMP_FILE_DIR, "/", name])
            os.remove(part_file_path)



